4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
11 // You must not remove this notice, or any other, from this software.
16 namespace Microsoft
.JScript
{
18 using System
.Collections
;
19 using System
.Reflection
;
20 using System
.Reflection
.Emit
;
21 using System
.Security
;
22 using System
.Security
.Permissions
;
23 using System
.Threading
;
24 using System
.Diagnostics
;
26 public abstract class MethodInvoker
{
29 [DebuggerStepThroughAttribute
]
30 [DebuggerHiddenAttribute
]
32 public abstract Object
Invoke(Object thisob
, Object
[] parameters
);
35 private static SimpleHashtable invokerFor
= new SimpleHashtable(64);
36 private static int count
= 0;
38 private static bool DoesCallerRequireFullTrust(MethodInfo method
){
39 Assembly assembly
= method
.DeclaringType
.Assembly
;
40 // strongly-named assembly requires full trust or AllowPartiallyTrustedCallersAttribute to be called
41 FileIOPermission pathDiscoveryPermission
= new FileIOPermission(PermissionState
.None
);
42 pathDiscoveryPermission
.AllFiles
= FileIOPermissionAccess
.PathDiscovery
;
43 pathDiscoveryPermission
.Assert();
44 byte[] key
= assembly
.GetName().GetPublicKey();
45 if (key
== null || key
.Length
== 0)
47 if (CustomAttribute
.GetCustomAttributes(assembly
, typeof(AllowPartiallyTrustedCallersAttribute
), true).Length
!= 0)
52 internal static MethodInvoker
GetInvokerFor(MethodInfo method
){
53 // .NET security does not allow Deny, Assert or PermitOnly to be called via
54 // Reflection. We are effectively creating our own Reflection layer, so
55 // we must do the same thing.
56 if (method
.DeclaringType
== typeof(System
.Security
.CodeAccessPermission
) && (method
.Name
== "Deny" || method
.Name
== "Assert" || method
.Name
== "PermitOnly"))
57 throw new JScriptException(JSError
.CannotCallSecurityMethodLateBound
);
59 MethodInvoker invoker
= MethodInvoker
.invokerFor
[method
] as MethodInvoker
;
60 if (invoker
!= null) return invoker
;
61 if (!SafeToCall(method
)) return null;
62 bool requiresDemand
= DoesCallerRequireFullTrust(method
);
63 lock(MethodInvoker
.invokerFor
){
64 invoker
= MethodInvoker
.invokerFor
[method
] as MethodInvoker
;
65 if (invoker
!= null) return invoker
;
66 invoker
= MethodInvoker
.SpitAndInstantiateClassFor(method
, requiresDemand
);
67 MethodInvoker
.invokerFor
[method
] = invoker
;
72 private static bool SafeToCall(MethodInfo meth
){
73 Type t
= meth
.DeclaringType
;
76 && t
!= typeof(System
.Activator
)
77 && t
!= typeof(System
.AppDomain
)
78 && t
!= typeof(System
.IO
.IsolatedStorage
.IsolatedStorageFile
)
79 && t
!= typeof(System
.Reflection
.Emit
.MethodRental
)
80 && t
!= typeof(System
.Security
.SecurityManager
)
81 && !typeof(System
.Reflection
.Assembly
).IsAssignableFrom(t
)
82 && !typeof(System
.Reflection
.MemberInfo
).IsAssignableFrom(t
)
83 && !typeof(System
.Resources
.ResourceManager
).IsAssignableFrom(t
)
84 && !typeof(System
.Delegate
).IsAssignableFrom(t
)
85 && (t
.Attributes
& TypeAttributes
.HasSecurity
) == 0
86 && (meth
.Attributes
& MethodAttributes
.HasSecurity
) == 0
87 && (meth
.Attributes
& MethodAttributes
.PinvokeImpl
) == 0
91 [ReflectionPermission(SecurityAction
.Assert
, Unrestricted
= true)]
92 private static MethodInvoker
SpitAndInstantiateClassFor(MethodInfo method
, bool requiresDemand
){
93 TypeBuilder tb
= Runtime
.ThunkModuleBuilder
.DefineType("invoker"+MethodInvoker
.count
++, TypeAttributes
.Public
, typeof(MethodInvoker
));
94 MethodBuilder mb
= tb
.DefineMethod("Invoke", MethodAttributes
.Public
|MethodAttributes
.Virtual
|MethodAttributes
.ReuseSlot
,
95 typeof(Object
), new Type
[]{typeof(Object), typeof(Object[])}
);
98 mb
.AddDeclarativeSecurity(SecurityAction
.Demand
, new NamedPermissionSet("FullTrust"));
100 mb
.SetCustomAttribute(new CustomAttributeBuilder(Runtime
.TypeRefs
.debuggerStepThroughAttributeCtor
, new Object
[]{}));
101 mb
.SetCustomAttribute(new CustomAttributeBuilder(Runtime
.TypeRefs
.debuggerHiddenAttributeCtor
, new Object
[]{}));
103 ILGenerator il
= mb
.GetILGenerator();
104 if (!method
.DeclaringType
.IsPublic
)
105 method
= method
.GetBaseDefinition();
106 Type obT
= method
.DeclaringType
;
107 if (!method
.IsStatic
){
108 il
.Emit(OpCodes
.Ldarg_1
);
109 if (obT
.IsValueType
){
110 Convert
.EmitUnbox(il
, obT
, Type
.GetTypeCode(obT
));
111 Convert
.EmitLdloca(il
, obT
);
113 il
.Emit(OpCodes
.Castclass
, obT
);
116 ParameterInfo
[] parameters
= method
.GetParameters();
117 LocalBuilder
[] outTemps
= null;
118 for (int i
= 0, n
= parameters
.Length
; i
< n
; i
++){
119 il
.Emit(OpCodes
.Ldarg_2
);
120 ConstantWrapper
.TranslateToILInt(il
, i
);
121 Type pt
= parameters
[i
].ParameterType
;
123 pt
= pt
.GetElementType();
124 if (outTemps
== null) outTemps
= new LocalBuilder
[n
];
125 outTemps
[i
] = il
.DeclareLocal(pt
);
126 il
.Emit(OpCodes
.Ldelem_Ref
);
128 Convert
.EmitUnbox(il
, pt
, Type
.GetTypeCode(pt
));
129 il
.Emit(OpCodes
.Stloc
, outTemps
[i
]);
130 il
.Emit(OpCodes
.Ldloca
, outTemps
[i
]);
132 il
.Emit(OpCodes
.Ldelem_Ref
);
134 Convert
.EmitUnbox(il
, pt
, Type
.GetTypeCode(pt
));
137 if (!method
.IsStatic
&& method
.IsVirtual
&& !method
.IsFinal
&& (!obT
.IsSealed
|| !obT
.IsValueType
))
138 il
.Emit(OpCodes
.Callvirt
, method
);
140 il
.Emit(OpCodes
.Call
, method
);
141 Type rt
= method
.ReturnType
;
142 if (rt
== typeof(void))
143 il
.Emit(OpCodes
.Ldnull
);
144 else if (rt
.IsValueType
)
145 il
.Emit(OpCodes
.Box
, rt
);
146 if (outTemps
!= null){
147 for (int i
= 0, n
= parameters
.Length
; i
< n
; i
++){
148 LocalBuilder loc
= outTemps
[i
];
150 il
.Emit(OpCodes
.Ldarg_2
);
151 ConstantWrapper
.TranslateToILInt(il
, i
);
152 il
.Emit(OpCodes
.Ldloc
, loc
);
153 Type pt
= parameters
[i
].ParameterType
.GetElementType();
155 il
.Emit(OpCodes
.Box
, pt
);
156 il
.Emit(OpCodes
.Stelem_Ref
);
160 il
.Emit(OpCodes
.Ret
);
161 Type t
= tb
.CreateType();
162 return (MethodInvoker
)Activator
.CreateInstance(t
);